package org.monster.context.core;

import org.monster.context.core.file.FileCatalog;
import org.monster.context.core.file.FileMap;
import org.monster.context.exception.FileException;

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

/**
 * 网应用文件
 *
 * @author Monster
 */
public class WebAppsFile {

    /**
     * 分割表达式
     */
    protected static final String splitRegex = "\\\\" + File.separator;
    /**
     * 文件目录
     */
    private final FileCatalog catalog = new FileCatalog();
    /**
     * 公共文件
     */
    private List<File> commonFiles = new ArrayList<>();

    /**
     * 获取 应用下 集合
     * webapps下所有文件
     *
     * @return 文件 集合
     */
    public List<File> getAppsUnder() {
        return getFileUnder(new File(Constants.APPS_PATH));
    }

    /**
     * 获取 文件下 集合
     * 获取某一个文件夹下的的所有文件夹路径
     *
     * @param file 文件
     * @return 文件集合
     */
    public List<File> getFileUnder(File file) {
        List<File> list = new ArrayList<>();
        if (file != null) {
            if (file.exists()) {
                File[] files = file.listFiles();
                for (File f : files) {
                    if (f.isDirectory()) {
                        list.add(f);
                    }
                }
            }
        }
        return list;
    }

    /**
     * 获取 文件 集合
     * 获取文件下的所有路径（包含参数路径）
     *
     * @param file 文件
     * @return
     */
    public List<File> getFiles(File file) {
        List<File> files = getFileUnder(file);
        if (getFileUnder(file) != null) {
            files.add(file);
        }
        return files;
    }

    /**
     * 查找 应用文件夹
     * 寻找webapps目录下是否包含文件名项目名的路径
     *
     * @param appName 应用名
     * @return 应用文件夹
     */
    public File findAppFolder(String appName) {
        List<File> webApps = getAppsUnder();
        for (File webApp : webApps) {
            String[] str = webApp.getAbsolutePath().split(splitRegex);
            String cutName = str[str.length - 1];
            if (appName.equals(cutName)) {
                return webApp;
            }
        }
        return null;
    }

    /**
     * 生成 编译过文件夹
     *
     * @param webAppPath 网应用路径
     * @return 编译过文件夹
     */
    public String generateCompiledFolder(File webAppPath) {
        StringBuilder sb = new StringBuilder();
        if (webAppPath != null) {
            sb.append(webAppPath.getAbsolutePath())
                    .append(File.separator)
                    .append(Constants.BUILD)
                    .append(File.separator)
                    .append(Constants.CLASSESS);
        }
        return sb.toString();
    }

    /**
     * 创建 编译后文件夹
     *
     * @param appPath    应用路径
     * @param originFile 源文件
     * @return 编译后文件夹
     */
    @Deprecated
    public String createCompiledFolder(File appPath, File originFile) throws FileException {
        // webapp目录下的classess文件路径
        StringBuilder classes = new StringBuilder();
        classes.append(appPath).append(File.separator)
                .append(Constants.BUILD).append(File.separator)
                .append(Constants.CLASSESS);
        String path = classes.toString();
        // webapp目录下源文件路径
        StringBuilder origin = new StringBuilder();
        origin.append(appPath).append(File.separator).append(Constants.SOURCE_SRC); // 1024
        String originPath = origin.toString();
        originPath = originFile.getAbsolutePath().substring(
                originPath.length(), originFile.getAbsolutePath().length());
        originPath = path + originPath;
        originPath = originPath.substring(path.length(),
                originPath.lastIndexOf(File.separator));
        StringTokenizer tokenizer = new StringTokenizer(originPath);
        String strPKG = "";
        // 把路径分元素叠加路径后创建
        while (tokenizer.hasMoreTokens()) {
            String fileName = tokenizer.nextToken(File.separator);
            strPKG += File.separator + fileName;
            File file = new File(path + strPKG);
            if (!file.exists()) {
                if (!file.mkdirs()) {
                    throw new FileException("文件删除失败！");
                }
            }
        }
        return path + originPath;
    }

    /**
     * 递归遍历文件下的所有文件路径
     *
     * @param file 文件
     * @return 文件
     */
    public List<File> enteringFileUnder(File file) {
        commonFiles = new ArrayList<>();
        return scanFileUnder(file);
    }

    /**
     * 扫描 文件下
     *
     * @param file 文件
     * @return 文件 集合
     */
    public List<File> scanFileUnder(File file) {
        if (file != null) {
            File[] files = file.listFiles();
            for (File f : files) {
                if (f.isDirectory()) {
                    commonFiles.add(f);
                    scanFileUnder(f);
                } else {
                    commonFiles.add(f);
                }
            }
        }
        return Collections.unmodifiableList(commonFiles);
    }

    /**
     * 递归 文件
     *
     * @param file 文件夹
     */
    public void recFile(File file) {
        if (file.isFile()) {
            catalog.put(file.getAbsolutePath(), file.lastModified());
        } else {
            File[] files = file.listFiles();
            for (File f : files) {
                recFile(f);
            }
        }
    }

    /**
     * 过滤 扩展名
     * 过滤Source(Java)文件
     *
     * @param files      文件 集合
     * @param fileSuffix 文件后缀
     * @return
     */
    public List<File> filterSuffix(List<File> files, String fileSuffix) {
        List<File> tempFiles = new ArrayList<>();
        for (File file : files) {
            if (file.getAbsolutePath().endsWith(fileSuffix)) {
                tempFiles.add(file);
            }
        }
        return tempFiles;
    }

    /**
     * 是否 存在应用文件
     * 验证是否是一个有效的webapps
     *
     * @return 布尔
     */
    public boolean isContainsAppFile() {
        if (equalsFolder(Constants.CLASSESS)
                && (equalsFolder(Constants.WEB_CONTENT)
                || equalsFolder(Constants.WEB_INF))) {
            commonFiles.clear();
            return true;
        }
        commonFiles.clear();
        return false;
    }

    /**
     * @return
     */
    public boolean isContainsAppFileNotClear() {
        return equalsFolder(Constants.CLASSESS)
                && (equalsFolder(Constants.WEB_CONTENT)
                || equalsFolder(Constants.WEB_INF));
    }

    /**
     * 比较 文件夹
     * 匹配是否有必须的文件夹
     *
     * @param folder 文件夹
     * @return 布尔
     */
    public boolean equalsFolder(String folder) {
        for (File file : commonFiles) {
            if (file != null && file.isDirectory()) {
                if (file.getName().equals(folder)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 添加 文件
     * 添加给定路径集合的所有文件和文件夹到webAppName目录下 具体实现的功能方法（不通用）
     *
     * @param files   文件 集合
     * @param appName 应用名
     * @param target  目标
     */
    public void addFiles(List<File> files, String appName, File target) throws IOException, FileException {
        if (target.exists()) {
            for (File prepareFile : files) {
                String preparePath = prepareFile.getAbsolutePath();
                preparePath = preparePath.substring(
                        preparePath.indexOf(appName), preparePath.length());
                File fileUnder = new File(target.getAbsolutePath()
                        + preparePath.substring(appName.length(),
                        preparePath.length()));
                if (prepareFile.isDirectory()) {
                    if (!fileUnder.mkdirs()) {
                        throw new FileException("文件夹创建失败！");
                    }
                }
                copyFile(prepareFile, fileUnder);
            }
        }
    }

    /**
     * 拷贝 文件
     * 给定要复制的文件，复制到目标文件路径下
     *
     * @param origin 源
     * @param target 目标
     * @throws FileNotFoundException 文件未找到异常
     */
    public void copyFile(File origin, File target) throws IOException {
        if (origin.exists() && !target.exists()) {
            FileInputStream input = new FileInputStream(origin);
            FileOutputStream output = new FileOutputStream(target);
            byte[] buffer = new byte[2048];
            int len;
            while ((len = input.read(buffer, 0, buffer.length)) != -1) {
                output.write(buffer, 0, len);
            }
            input.close();
            output.close();
        }
    }

    /**
     * 拷贝 文件夹
     * 复制一个文件下的所有子文件夹到目标文件夹下
     *
     * @param origin 源
     * @param target 目标
     * @throws FileNotFoundException 文件未找到异常
     */
    public void copyFolder(File origin, File target)
            throws FileNotFoundException, FileException {
        if (origin.exists() && origin.isDirectory() && !target.exists()
                && target.isDirectory()) {
            if (!target.mkdirs()) {
                throw new FileException("文件夹创建失败！");
            }
        }
    }

    /**
     * 文件判断，判断对象下的引用目标是否存在
     *
     * @param path 路径
     * @return 布尔
     */
    public boolean existsFileQuote(String path) {
        return existsFileQuote(new File(path));
    }

    /**
     * 文件判断，判断对象下的引用目标是否存在
     *
     * @param file 文件
     * @return 布尔
     */
    public boolean existsFileQuote(File file) {
        return file.exists();
    }

    /**
     * 截取文件路径的末尾文件名
     *
     * @param path 路径
     * @return 文件名
     */
    public String endsWithFileName(String path) {
        String[] split = path.split(splitRegex);
        return split[split.length - 1];
    }

    /**
     * 移除 文件
     *
     * @param file 文件
     */
    public void removeFiles(File file) throws FileException {
        if (file != null) {
            if (!file.delete()) {
                throw new FileException("文件删除失败！");
            }
            if (file.isDirectory()) {
                file.delete();
                File[] files = file.listFiles();
                for (File f : files) {
                    removeFiles(f);
                }
            }
        }
    }

    /**
     * 移除 文件
     *
     * @param file 文件
     */
    public void removeFolder(File file) throws FileException {
        if (file != null) {
            if (!file.delete()) {
                throw new FileException("文件删除失败！");
            }
            File[] files = file.listFiles();
            if (files != null) {
                for (File f : files) {
                    if (!file.delete()) {
                        throw new FileException("文件删除失败！");
                    }
                    removeFolder(f);
                }
            }
        }
    }

    /**
     * 移除 文件 集合
     *
     * @param files 文件 集合
     */
    public void removeFiles(List<File> files) throws FileException {
        List<FileMap> fileMap = new ArrayList<>();
        int j = 0;
        int len;
        for (File file : files) {
            String[] split = file.getAbsolutePath().split("\\\\");
            len = split.length;
            fileMap.add(new FileMap(len, file.getAbsolutePath()));
            if (split.length > j) {
                j = split.length;
            }
        }
        for (int i = j; i >= 0; i--) {
            for (FileMap fileId : fileMap) {
                if (fileId.getLen() == i) {
                    File file = new File(fileId.getName());
                    if (!file.delete()) {
                        throw new FileException("文件删除失败！");
                    }
                }
            }
        }
    }
}
